package com.xiaozhen.quartz.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaozhen.quartz.config.BaseJob;
import com.xiaozhen.quartz.config.JobAndTrigger;
import com.xiaozhen.quartz.service.JobService;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhenweisheng
 * @date 2020/9/30 9:09
 * @description:
 */
@Service
public class JobServiceImpl implements JobService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public void addJob(String jobClassName, String jobGroupName,
                       String cronExpression, String jobName) throws Exception {
        // 启动调度器
        scheduler.start();
        // 构建job信息
        JobDetail jobDetail = JobBuilder
                .newJob(getClass(jobClassName).getClass())
                .withIdentity(jobName, jobGroupName).build();

        // 表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                .cronSchedule(cronExpression);

        // 按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, jobGroupName)
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            System.out.println("创建定时任务失败" + e);
            throw new Exception("创建定时任务失败");
        }
    }

    @Override
    public void addDailyTimeIntervalJob(String jobClassName,
                                        String jobGroupName, String jobName, String startTime,
                                        String endTime, Integer inteval) throws Exception {
        // 启动调度器
        scheduler.start();

        // 构建job信息
        JobDetail jobDetail = JobBuilder
                .newJob(getClass(jobClassName).getClass())
                .withIdentity(jobName, jobGroupName).build();
        String[] split = startTime.split(":");
        String[] split2 = endTime.split(":");

        // 表达式调度构建器(即任务执行的时间)
        DailyTimeIntervalScheduleBuilder scheduleBuilder = DailyTimeIntervalScheduleBuilder
                .dailyTimeIntervalSchedule()
                .startingDailyAt(
                        TimeOfDay.hourAndMinuteOfDay(
                                Integer.parseInt(split[0]),
                                Integer.parseInt(split[1]))) // 第天9：00开始
                .endingDailyAt(
                        TimeOfDay.hourAndMinuteOfDay(
                                Integer.parseInt(split2[0]),
                                Integer.parseInt(split2[1]))) // 16：00 结束
                .withIntervalInMinutes(inteval); // 每间隔inteval分钟执行一次

        // 按新的cronExpression表达式构建一个新的trigger
        DailyTimeIntervalTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, jobGroupName)
                .withSchedule(scheduleBuilder).build();

        try {
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException e) {
            System.out.println("创建定时任务失败" + e);
        }
    }

    @Override
    public void jobPause(String jobName, String jobGroupName) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @Override
    public void jobResume(String jobName, String jobGroupName) throws Exception {
        scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @Override
    public void jobReschedule(String jobName, String jobGroupName,
                              String cronExpression) throws Exception {
        try {
            TriggerKey triggerKey = TriggerKey
                    .triggerKey(jobName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                    .cronSchedule(cronExpression);

            CronTrigger trigger = (CronTrigger) scheduler
                    .getTrigger(triggerKey);

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            System.out.println("更新定时任务失败" + e);
            throw new Exception("更新定时任务失败");
        }
    }

    @Override
    public void jobDelete(String jobName, String jobGroupName) throws Exception {
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @Override
    public void jobDeleteAll() throws Exception {
        List<JobAndTrigger> list = new ArrayList<>();
        try {
            for (String groupJob : scheduler.getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
                        .<JobKey>groupEquals(groupJob))) {
                    List<? extends Trigger> triggers = scheduler
                            .getTriggersOfJob(jobKey);
                    for (Trigger trigger : triggers) {
                        String cronExpression = "";
                        String tIME_ZONE_ID = "";
                        if (trigger instanceof CronTrigger) {
                            CronTrigger cronTrigger = (CronTrigger) trigger;
                            cronExpression = cronTrigger.getCronExpression();
                            tIME_ZONE_ID = cronTrigger.getTimeZone().getID();
                        }
                        JobAndTrigger jobAndTrigger = new JobAndTrigger();
                        jobAndTrigger.setJobName(jobKey.getName());
                        jobAndTrigger.setJobGroup(jobKey.getGroup());
                        jobAndTrigger.setTriggerGroup(jobKey.getGroup());
                        jobAndTrigger.setTriggerName(jobKey.getName());
                        jobAndTrigger.setCronExpression(cronExpression);
                        jobAndTrigger.setTimeZoneId(tIME_ZONE_ID);
                        list.add(jobAndTrigger);
                    }
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < list.size(); i++) {
            String jobName = list.get(i).getJobName();
            String jobGroupName = list.get(i).getJobGroup();
            try {
                jobDelete(jobName, jobGroupName);
            } catch (Exception e) {
                System.out.println(jobGroupName + "......" + jobName);
            }
        }
    }

    @Override
    public Page<JobAndTrigger> queryJob(Integer pageNum, Integer pageSize) {
        List<JobAndTrigger> list = new ArrayList<>();
        int i = 0;
        try {
            for (String groupJob : scheduler.getJobGroupNames()) {
                for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
                        .<JobKey>groupEquals(groupJob))) {
                    List<? extends Trigger> triggers = scheduler
                            .getTriggersOfJob(jobKey);
                    JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                    for (Trigger trigger : triggers) {
                        String cronExpression = "";
                        String tIME_ZONE_ID = "";
                        if (trigger instanceof CronTrigger) {
                            CronTrigger cronTrigger = (CronTrigger) trigger;
                            cronExpression = cronTrigger.getCronExpression();
                            tIME_ZONE_ID = cronTrigger.getTimeZone().getID();
                        }
                        JobAndTrigger jobAndTrigger = new JobAndTrigger();
                        jobAndTrigger.setJobClassName(jobDetail.getJobClass().getCanonicalName());
                        jobAndTrigger.setJobName(jobKey.getName());
                        jobAndTrigger.setJobGroup(jobKey.getGroup());
                        jobAndTrigger.setTriggerGroup(trigger.getKey().getGroup());
                        jobAndTrigger.setTriggerName(trigger.getKey().getName());
                        jobAndTrigger.setCronExpression(cronExpression);
                        jobAndTrigger.setTimeZoneId(tIME_ZONE_ID);
                        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                        jobAndTrigger.setTriggerState(triggerState.name());
                        if (i >= (pageNum - 1) * pageSize
                                && i < pageNum * pageSize) {
                            list.add(jobAndTrigger);
                        }
                        i++;
                    }
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        Page<JobAndTrigger> page = new Page<>();
        page.setRecords(list);
        page.setTotal(i);
        return page;
    }


    public static BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.getDeclaredConstructor().newInstance();
    }
}

